import React, { memo } from "react";
import ReactDOM from "react-dom";
// 实现useState, 修复使用多次useState出现的问题
// 通过定义个数组对象，以及stateIndex索引，每次调用useState都把索引增加，可以进行区别不同的useState
let lastStates = [];
let stateIndex = 0;
function useState(initialState) {
  lastStates[stateIndex] = lastStates[stateIndex] || initialState;
  let currentIndex = stateIndex;
  function setState(newState) {
    lastStates[currentIndex] = newState;
    render();
    stateIndex = 0;
  }
  return [lastStates[stateIndex++], setState];
}
let lastMemo;
let lastMemoDependencies;
function useMemo(callback, dependencies) {
  if (lastMemoDependencies) {
    let changed = dependencies.some((item, index) => {
      return item !== lastMemoDependencies[index];
    });
    if (changed) {
      lastMemo = callback();
      lastMemoDependencies = dependencies;
    }
  } else {
    lastMemo = callback();
    lastMemoDependencies = dependencies;
  }
  return lastMemo;
}
let lastCallback;
let lastCallbackDependencies;
function useCallback(callback, dependencies) {
  if (lastCallbackDependencies) {
    let changed = dependencies.some((item, index) => {
      return item !== lastCallbackDependencies[index];
    });
    if (changed) {
      lastCallback = callback;
      lastCallbackDependencies = dependencies;
    }
  } else {
    lastCallback = callback;
    lastCallbackDependencies = dependencies;
  }
  return lastCallback;
}
// 此时会存在性能问题，如果更新父组件，即使没有改动子元素的数据，子元素也会进行更新，可以使用useMemo
function App() {
  // 定义num值为0，并设置一个改变num值的方法setNum
  const [num, setNum] = useState(0);
  const [name, setName] = useState("state");
  // useMemo用于缓存对象数据，
  // 第二个参数是依赖项，控制number依赖哪个数据进行变化，
  // [num] 依赖num数据的变化而变化
  // 如果为[]，点击按钮触发的事件就会失效，无法判断依赖项；
  // 如果不填写就会一直变,触发父组件的name,子组件也会render
  let number = useMemo(() => num, [num]);
  // useCallback用于缓存函数
  // 第二个参数是依赖项，控制addClick依赖哪个数据进行变化，
  // 如果为[]就会根据第一个参数中的函数的返回值进行变化；如果不填写就会一直变,触发父组件的name,子组件也会render
  let addClick = useCallback(() => setNum(num + 1), [num]);
  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <Child number={number} addClick={addClick} />
    </div>
  );
}
function Child({ number, addClick }) {
  // 当每次更新父组件name的值时，也会执行Child组件的render，如果子组件非常庞大造成性能的影响
  console.log("render child");
  return <button onClick={addClick}>{number}</button>;
}
// memo对组件的缓存
Child = memo(Child);
function render() {
  ReactDOM.render(<App />, document.getElementById("root"));
}
render();
